﻿using System;
using System.Collections.Generic;
using System.Text;
using Algoritmi;
using System.ComponentModel;
using System.Timers;

namespace AlgorithmStarter
{
    public class AlgorithmsManager
    {
        enum states
        {
            notInitialized,
            initialized,
            ignorePhase,
            runPhase,
            completed
        }

        states state = states.notInitialized;
        IAlgorithm activeAlgorithm;
        object[] parameters;
        CommunicationsManager commManager;
        BackgroundWorker worker;
        Timer t;

        public AlgorithmsManager(CommunicationsManager commManager)
        {
            this.commManager = commManager;
            worker = new BackgroundWorker();
            worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            t = new Timer();
            t.AutoReset = false;
            t.Elapsed += new ElapsedEventHandler(t_Elapsed);
            t.Interval = 500;
            t.Enabled = true;
        }

        void t_Elapsed(object sender, ElapsedEventArgs e)
        {
            switch (state)
            {
                case states.notInitialized:
                    break;
                case states.initialized:
                    CallIgnorePhase();
                    break;
                case states.ignorePhase:
                    CallRunPhase();
                    break;
                case states.runPhase:
                    break;
                case states.completed:
                    break;
                default:
                    break;
            }
        }

        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            switch (state)
            {
                case states.notInitialized:
                    break;
                case states.initialized:
                    break;
                case states.ignorePhase:
                    {
                        IgnorePhase mex = new IgnorePhase();
                        commManager.InviaMessaggio(mex);
                        activeAlgorithm.setParams(parameters);
                        activeAlgorithm.ignorePhase();
                        break;
                    }
                case states.runPhase:
                    {
                        RunPhase mex = new RunPhase();
                        commManager.InviaMessaggio(mex);
                        activeAlgorithm.runPhase();
                        break;
                    }
                case states.completed:
                    break;
                default:
                    break;
            }
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            switch (state)
            {
                case states.notInitialized:
                    break;
                case states.initialized:
                    break;
                case states.ignorePhase:
                    {
                        IgnorePhaseCompleted mex = new IgnorePhaseCompleted();
                        commManager.InviaMessaggio(mex);
                        if (OnIgnorePhaseCompleted != null)
                            OnIgnorePhaseCompleted();
                        t.Start();
                        break;
                    }
                case states.runPhase:
                    {
                        RunPhaseCompleted mex = new RunPhaseCompleted();
                        commManager.InviaMessaggio(mex);
                        if (OnRunPhaseCompleted != null)
                            OnRunPhaseCompleted();
                        break;
                    }
                case states.completed:
                    break;
                default:
                    break;
            }
        }

        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
        }

        public void CallSetAlgorithm(Message mex)
        {
            SetAlgorithm sa = mex as SetAlgorithm;
            parameters = sa.algorithmParams;
            switch (sa.algorithmName)
            {
                case "Energon":
                    {
                        activeAlgorithm = new Energon();
                    }
                    break;
                case "k-Energon":
                    {
                        activeAlgorithm = new KEnergon();
                    }
                    break;
                case "SimpleLoopCSharp":
                    {
                        activeAlgorithm = new SimpleLoopCSharp();
                    }
                    break;
                case "SimpleLoopCSharpTest":
                    {
                        activeAlgorithm = new SimpleLoopCSharpTest();
                    }
                    break;
                case "f":
                    {
                        activeAlgorithm = new f();
                    }
                    break;
                case "g":
                    {
                        activeAlgorithm = new g();
                    }
                    break;
                case "f_plus_g":
                    {
                        activeAlgorithm = new f_plus_g();
                    }
                    break;
                case "f_dot_g":
                    {
                        activeAlgorithm = new f_dot_g();
                    }
                    break;
                default:
                    break;
            }
            state = states.initialized;
            //CallIgnorePhase();
            t.Start();
        }

        public void CallIgnorePhase()
        {
            state = states.ignorePhase;
            worker.RunWorkerAsync();
        }

        public void CallRunPhase()
        {
            state = states.runPhase;
            worker.RunWorkerAsync();
        }

        public delegate void IgnorePhaseCompletedDelegate();
        public event IgnorePhaseCompletedDelegate OnIgnorePhaseCompleted;

        public delegate void RunPhaseCompletedDelegate();
        public event RunPhaseCompletedDelegate OnRunPhaseCompleted;

    }
}
